fix(nextjs): skip invalidateCacheAction on Next.js 15+ for all auth transitions#7873
fix(nextjs): skip invalidateCacheAction on Next.js 15+ for all auth transitions#7873jacekradko wants to merge 1 commit intomainfrom
Conversation
…ransitions
On Next.js 15+, calling `invalidateCacheAction()` during sign-in triggers
`cookies().delete()`, which causes Next.js to re-render the current page's
RSC tree as part of the server action response. In Safari, this RSC delivery
fails ("TypeError: Load failed"), causing Next.js to fall back to a hard
browser navigation. For flows using one-time tokens (e.g. impersonation via
`__clerk_ticket`), the hard reload re-submits the spent token, resulting in
a 400 error.
The server action was already skipped for sign-out on Next.js 15+ (to avoid
404/405 errors on protected pages). This extends the skip to all auth state
transitions, relying on `router.refresh()` in `onAfterSetActive` for cache
invalidation — which is sufficient given the less aggressive router cache in
Next.js 15+.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
📝 WalkthroughWalkthroughModified the 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
@clerk/agent-toolkit
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/dev-cli
@clerk/expo
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/hono
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
|
!snapshot |
|
Hey @jacekradko - the snapshot version command generated the following package versions:
Tip: Use the snippet copy button below to quickly install the required packages. npm i @clerk/agent-toolkit@0.3.0-snapshot.v20260218023153 --save-exact
npm i @clerk/astro@3.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/backend@3.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/chrome-extension@3.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/clerk-js@6.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/dev-cli@1.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/expo@3.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/expo-passkeys@1.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/express@2.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/fastify@2.7.0-snapshot.v20260218023153 --save-exact
npm i @clerk/localizations@4.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/msw@0.0.1-snapshot.v20260218023153 --save-exact
npm i @clerk/nextjs@7.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/nuxt@2.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/react@6.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/react-router@3.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/shared@4.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/tanstack-react-start@1.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/testing@2.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/ui@1.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/upgrade@2.0.0-snapshot.v20260218023153 --save-exact
npm i @clerk/vue@2.0.0-snapshot.v20260218023153 --save-exact |
|
I get this was probably a work in progress attempt to fix things, but it seems like the real culprit was the |
|
@Ephem Yep, that is correct |
Testing this out. Not ready for review
Summary
Fixes OTP and impersonation sign-in failing in Safari on the dashboard (Next.js 15+/16).
Root cause
invalidateCacheAction()callscookies().delete()inside a server action duringonBeforeSetActive. In Next.js 15+, this triggers an automatic re-render of the current page's RSC tree as part of the server action response. In Safari, this RSC delivery fails (TypeError: Load failed), causing Next.js to fall back to a hard browser navigation (full page reload).For impersonation flows, the reload navigates back to
/sign-in?__clerk_ticket=<token>(the URL from Next.js's internal router state, whichhistory.replaceStatedoesn't update). The sign-in page re-submits the already-consumed one-time token, resulting in a 400 error ("This actor token has already been used").For OTP flows, the hard reload loses the sign-in state, forcing the user to restart.
Fix
The server action was already skipped for sign-out on Next.js 15+ (to avoid 404/405 errors on Vercel for protected pages). This PR extends the skip to all auth state transitions on Next.js 15+, relying on
router.refresh()inonAfterSetActivefor cache invalidation — which is sufficient given the less aggressive router cache in Next.js 15+.What changed
packages/nextjs/src/app-router/client/ClerkProvider.tsx: Removed&& intent === 'sign-out'condition from the Next.js 15+ check, soinvalidateCacheAction()is skipped for all auth transitions (not just sign-out)Test plan
Relates to USER-4720
Summary by CodeRabbit
Release Notes
Refactor
Documentation